package com.xxl.job.executor.hktv.basics;

import com.xxl.job.executor.hktv.ClientDemo.HCNetSDK;
import com.xxl.job.executor.utils.*;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Encoder;

import javax.swing.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Author: SONGtiank
 * @Description: 海康sdk服务类
 * @Date: 2020/11/3 9:50
 * @Version: 1.0
 */
public class HikVisionService {
    private static Logger logger = LoggerFactory.getLogger(HikVisionService.class);
    static HCNetSDK hCNetSDK = HCNetSDK.INSTANCE;
    static String m_sUsername = "admin";//设备用户名
    static String m_sPassword = "hk123456";//设备密码
    static short m_sPort = 8000;//端口号，这是默认的
    public NativeLong lUserID;//用户句柄
    public NativeLong lAlarmHandle;//报警布防句柄
    public int lListenHandle;//报警监听句柄
    public NativeLong RemoteConfig;
    public static int code = 5;

    //撤防
    public void CloseAlarmChan() {
        //报警撤防
        if (lAlarmHandle.intValue() > -1) {
            if (hCNetSDK.NET_DVR_CloseAlarmChan_V30(lAlarmHandle.intValue())) {
                System.out.println("撤防成功");
                lAlarmHandle = new NativeLong(-1);
            }
        }
    }

    public void initMemberFlowUpload(String m_sDeviceIP, int remainMinuteTime) throws InterruptedException {
        // 初始化
        Boolean flag = hCNetSDK.NET_DVR_Init();
        if (flag) {
            System.out.println("初始化成功");
        } else {
            System.out.println("初始化失败");
        }
        //设置连接时间与重连时间
        hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
        hCNetSDK.NET_DVR_SetReconnect(100000, true);
        //设备信息, 输出参数
        HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
        HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
        // 注册设备-登录参数，包括设备地址、登录用户、密码等
        m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
        m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
        m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
        System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
        m_strLoginInfo.wPort = m_sPort;
        m_strLoginInfo.bUseAsynLogin = false; //是否异步登录：0- 否，1- 是
        m_strLoginInfo.write();
        //设备信息, 输出参数
        int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
        if (lUserID < 0) {
            System.out.println("hCNetSDK.NET_DVR_Login_V30()" + "\n" + hCNetSDK.NET_DVR_GetErrorMsg(null));
            hCNetSDK.NET_DVR_Cleanup();
            return;
        }
        //设置报警回调函数
        if (!hCNetSDK.NET_DVR_SetDVRMessageCallBack_V31(this::MsesGCallBack, null)) {
            System.out.println("设置回调函数失败" + hCNetSDK.NET_DVR_GetLastError());
            return;
        } else {
            System.out.println("设置回调函数成功");
        }
        //启用布防
        HCNetSDK.NET_DVR_SETUPALARM_PARAM lpSetupParam = new HCNetSDK.NET_DVR_SETUPALARM_PARAM();
        lpSetupParam.dwSize = 0;
        lpSetupParam.byLevel = 1;//布防优先级：0- 一等级（高），1- 二等级（中）
        lpSetupParam.byAlarmInfoType = 1;//上传报警信息类型: 0- 老报警信息(NET_DVR_PLATE_RESULT), 1- 新报警信息(NET_ITS_PLATE_RESULT)
        int lAlarmHandle = hCNetSDK.NET_DVR_SetupAlarmChan_V41(lUserID, lpSetupParam);
        if (lAlarmHandle < 0) {
            System.out.println("NET_DVR_SetupAlarmChan_V41 error, %d\n" + hCNetSDK.NET_DVR_GetLastError());
            hCNetSDK.NET_DVR_Logout(lUserID);
            hCNetSDK.NET_DVR_Cleanup();
            return;
        }
        System.out.println("布防成功,开始监测车辆");
        //启动监听----------------------------------------------
        int iListenPort = 8000;
        String m_sListenIP = "127.0.0.1";
        lListenHandle = hCNetSDK.NET_DVR_StartListen_V30(m_sListenIP, (short) iListenPort, this::MsesGCallBack, null);
        if (lListenHandle < 0) {
            System.out.println("启动监听失败，错误号:" + hCNetSDK.NET_DVR_GetLastError());
        } else {
            System.out.println("启动监听成功");
        }


    }

    public boolean MsesGCallBack(int lCommand, HCNetSDK.NET_DVR_ALARMER pAlarmer, Pointer pAlarmInfo, int dwBufLen, Pointer pUser) {
        /*System.out.println("〈－－进入回调,开始识别车牌－－〉"+ new String(pAlarmer.sDeviceIP).trim());*/
        logger.info("〈－－进入回调,开始识别车牌－－〉"+ new String(pAlarmer.sDeviceIP).trim());
        try {
            String sAlarmType = new String();
            String[] newRow = new String[3];
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
            String imgName = sf.format(new Date()) + ".jpg";
            String clImgName = "cl" + sf.format(new Date()) + ".jpg";
            String[] sIP = new String[2];
            switch (lCommand) {
                case 0x2800:    //交通抓拍结果上传
                    HCNetSDK.NET_DVR_PLATE_RESULT strPlateResult = new HCNetSDK.NET_DVR_PLATE_RESULT();
                    strPlateResult.write();
                    Pointer pPlateInfo = strPlateResult.getPointer();
                    pPlateInfo.write(0, pAlarmInfo.getByteArray(0, strPlateResult.size()), 0, strPlateResult.size());
                    strPlateResult.read();
                    try {
                        String srt3 = new String(strPlateResult.struPlateInfo.sLicense, "GBK");
                        logger.info("0x2800" + srt3);
                        sAlarmType = sAlarmType + ":抓拍上传，车牌：" + srt3;
                    } catch (UnsupportedEncodingException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    newRow[0] = dateFormat.format(new Date());
                    //报警类型
                    newRow[1] = sAlarmType;
                    //报警设备IP地址
                    sIP = new String(pAlarmer.sDeviceIP).split("\0", 2);
                    newRow[2] = sIP[0];
                    break;
                case 0x3050:    //交通抓拍的终端图片上传
                    HCNetSDK.NET_ITS_PLATE_RESULT strItsPlateResult = new HCNetSDK.NET_ITS_PLATE_RESULT();
                    strItsPlateResult.write();
                    Pointer pItsPlateInfo = strItsPlateResult.getPointer();
                    pItsPlateInfo.write(0, pAlarmInfo.getByteArray(0, strItsPlateResult.size()), 0, strItsPlateResult.size());
                    strItsPlateResult.read();
                    try {
                        Map<String, String> paramMap = new HashMap<String, String>();
                        String plateStr = new String(strItsPlateResult.struPlateInfo.sLicense, "GBK");
                        if (!"车牌".equals(plateStr.substring(1, plateStr.length()).trim())) {
                            paramMap.put("vehicleId", plateStr.substring(1, plateStr.length()).trim()); //车牌号
                            paramMap.put("vehicleColor", plateStr.substring(0, 1).trim());//车牌颜色
                            paramMap.put("vehicleTypeId", PlateType.getPlateType(strItsPlateResult.struPlateInfo.byPlateType + "".trim()));//车牌种类ID
                            paramMap.put("vehicleType", PlateTypeName.getPlateTypeName(PlateType.getPlateType(strItsPlateResult.struPlateInfo.byPlateType + "".trim())));//车牌种类
                            paramMap.put("vehicleModelId", CarType.getCarType(strItsPlateResult.byVehicleType + "".trim()));//	 车型号
                            paramMap.put("vehicleModelName", CarTypeName.getCarType(CarType.getCarType(strItsPlateResult.byVehicleType + "".trim())));// 车型名称 必
                            paramMap.put("bodyColor", ColorType.getColorType(strItsPlateResult.struVehicleInfo.byColor + "".trim()));//车牌颜色
                            paramMap.put("cameraIp", new String(pAlarmer.sDeviceIP).trim());//ip地址
                            paramMap.put("speed", strItsPlateResult.struVehicleInfo.wSpeed + "".trim());//速度
                            paramMap.put("evenTypeId", strItsPlateResult.wIllegalType + "".trim());//事件ID
                            paramMap.put("evenTypeName", BreakRulesType.getBreakRulesType(strItsPlateResult.wIllegalType));//事件名称
                            paramMap.put("direction", AirType.getAirType(strItsPlateResult.byCarDirectionType + "".trim()));//方向
                            String carFileName = "D:\\carImg\\" + new String(pAlarmer.sDeviceIP).trim() + "\\";
                            for (int i = 0; i < strItsPlateResult.dwPicNum; i++) {
                                if (strItsPlateResult.struPicInfo[i].dwDataLen > 0) {
                                    if (strItsPlateResult.struPicInfo[i].byType == 1) {//车辆场景图片
                                        FileOutputStream fout;
                                        if (strItsPlateResult.struPicInfo[i].byType == 1) {//车辆场景图片
                                            File file = new File(carFileName + clImgName);
                                            if (!file.getParentFile().exists()) {
                                                file.getParentFile().mkdirs();
                                            }
                                            fout = new FileOutputStream(carFileName + clImgName);
                                            //将字节写入文件
                                            long offset = 0;
                                            ByteBuffer buffers = strItsPlateResult.struPicInfo[i].pBuffer.getByteBuffer(offset, strItsPlateResult.struPicInfo[i].dwDataLen);
                                            byte[] bytes = new byte[strItsPlateResult.struPicInfo[i].dwDataLen];
                                            buffers.rewind();
                                            buffers.get(bytes);
                                            fout.write(bytes);
                                            fout.close();
                                            paramMap.put("imagefile", ApiUtils.ConvertImageToBase64(file));
                                            break;
                                        }
                                    }
                                }
                            }
                            logger.info("识别信息：---》" + new String(pAlarmer.sDeviceIP).trim() + paramMap.toString());

                        }
                    } catch (UnsupportedEncodingException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    break;
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}